/**
 * @file storage_nor.h
 * @author LokLiang (lokliang@163.com)
 * @brief 定义 Nor Flash 的操作接口
 * @version 0.1
 * @date 2023-06-02 定义框架
 *
 * @copyright Copyright (c) 2023
 *
 */

#ifndef __STORAGE_NOR_H__
#define __STORAGE_NOR_H__

/* Includes ------------------------------------------------------------------*/

#include "sys_init.h"

#ifdef __cplusplus
extern "C" {
#endif /* #ifdef __cplusplus */

/* Macros --------------------------------------------------------------------*/

/* Typedef -------------------------------------------------------------------*/

typedef const struct storage_nor *storage_nor_t;

typedef void (*storage_nor_read_cb)(storage_nor_t nor_hdl, void *arg);

/* Function prototypes -------------------------------------------------------*/

__static_inline storage_nor_t nor_binding(const char *component_name);
__static_inline const char *nor_search(const char *prefix_name, unsigned int num);

__static_inline int nor_init(storage_nor_t nor_hdl, const char *device_name, void *arg);
__static_inline int nor_deinit(storage_nor_t nor_hdl);

__static_inline void nor_lock(storage_nor_t nor_hdl);
__static_inline void nor_unlock(storage_nor_t nor_hdl);

__static_inline uint16_t nor_get_sector_size(storage_nor_t nor_hdl);
__static_inline uint32_t nor_get_chip_size(storage_nor_t nor_hdl);

__static_inline int nor_erase(storage_nor_t nor_hdl, uint32_t addr, uint32_t size);
__static_inline int nor_write(storage_nor_t nor_hdl, uint32_t addr, const void *src, uint32_t size);

__static_inline int nor_read(storage_nor_t nor_hdl, void *dest, uint32_t addr, uint32_t size);
__static_inline int nor_read_async(storage_nor_t nor_hdl, void *dest, uint32_t addr, uint32_t size, storage_nor_read_cb cb, void *arg);

__static_inline int nor_is_busy(storage_nor_t nor_hdl);

__static_inline int nor_set_power(storage_nor_t nor_hdl, bool power_on);

/* Code ----------------------------------------------------------------------*/

typedef struct
{
    int (*init)(storage_nor_t nor_hdl, const char *device_name, void *arg);
    int (*deinit)(storage_nor_t nor_hdl);
    void (*lock)(storage_nor_t nor_hdl);
    void (*unlock)(storage_nor_t nor_hdl);
    uint16_t (*get_sector_size)(storage_nor_t nor_hdl);
    uint32_t (*get_chip_size)(storage_nor_t nor_hdl);
    int (*erase)(storage_nor_t nor_hdl, uint32_t addr, uint32_t size);
    int (*write)(storage_nor_t nor_hdl, uint32_t addr, const void *src, uint32_t size);
    int (*read)(storage_nor_t nor_hdl, void *dest, uint32_t addr, uint32_t size);
    int (*read_async)(storage_nor_t nor_hdl, void *dest, uint32_t addr, uint32_t size, storage_nor_read_cb cb, void *arg);
    bool (*is_busy)(storage_nor_t nor_hdl);
    int (*set_power)(storage_nor_t nor_hdl, bool power_on);
} storage_nor_api_t;

typedef struct
{
    void *data;
} storage_nor_cfg_t;

struct storage_nor
{
    storage_nor_api_t api;
    storage_nor_cfg_t *cfg;
};

/**
 * @brief 绑定一个名为 component_name 的 nor 存储设备模块。
 * 模块的对象数据由 @c OBJ_EXPORT_COMPONENT 所定义。
 *
 * @param component_name 模块名称
 * @return storage_nor_t 设备对象，在应用前需要使用 nor_init() 进行初始化
 */
__static_inline storage_nor_t nor_binding(const char *component_name)
{
    return (storage_nor_t)component_binding(component_name);
}

/**
 * @brief 查找 nor_binding() 可用的模块对象名。
 *
 * @param prefix_name 模块对象名前缀。如 "NOR:"
 * @param num 匹配到 prefix_name 的第几次时返回，范围 0..n
 * @return const char * 匹配到的第 num 个名称为 prefix_name.* 的完整对象名
 * @return NULL 表示没对象
 */
__static_inline const char *nor_search(const char *prefix_name, unsigned int num)
{
    return component_search(prefix_name, num);
}

/**
 * @brief 执行初始化。在使用任何 API 前都需要先初始化。
 * 注意其中可能存在动态申请的内存，使用 nor_deinit() 释放其内存
 *
 * @param nor_hdl 来自 nor_binding() 取得的对象
 * @param device_name 设备名称。如 "SPI:"
 * @param arg 附带参数
 * @return int 0 表示操作成功；
 * @return int -1 表示对象无效或操作失败
 */
__static_inline int nor_init(storage_nor_t nor_hdl, const char *device_name, void *arg)
{
    if (nor_hdl)
        return nor_hdl->api.init(nor_hdl, device_name, arg);
    return -1;
}

/**
 * @brief 取消初始化
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @return int 0 表示操作成功；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败
 */
__static_inline int nor_deinit(storage_nor_t nor_hdl)
{
    if (nor_hdl)
        return nor_hdl->api.deinit(nor_hdl);
    return -1;
}

/**
 * @brief 锁定访问
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 */
__static_inline void nor_lock(storage_nor_t nor_hdl)
{
    if (nor_hdl)
        return nor_hdl->api.lock(nor_hdl);
}

/**
 * @brief 解锁
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 */
__static_inline void nor_unlock(storage_nor_t nor_hdl)
{
    if (nor_hdl)
        return nor_hdl->api.unlock(nor_hdl);
}

/**
 * @brief 获取存储器的扇区大小（可擦除的最小单元长度）
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @return uint16_t 字节
 */
__static_inline uint16_t nor_get_sector_size(storage_nor_t nor_hdl)
{
    if (nor_hdl)
        return nor_hdl->api.get_sector_size(nor_hdl);
    return 0;
}

/**
 * @brief 获取存储器的总大小
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @return uint32_t 字节
 */
__static_inline uint32_t nor_get_chip_size(storage_nor_t nor_hdl)
{
    if (nor_hdl)
        return nor_hdl->api.get_chip_size(nor_hdl);
    return 0;
}

/**
 * @brief 擦除指定的地址所在的扇区
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @param addr 操作的地址
 * @param size 字节
 * @return int 0 表示操作成功；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败
 */
__static_inline int nor_erase(storage_nor_t nor_hdl, uint32_t addr, uint32_t size)
{
    if (nor_hdl)
        return nor_hdl->api.erase(nor_hdl, addr, size);
    return -1;
}

/**
 * @brief 保存数据
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @param addr 操作的地址
 * @param src 来源数据
 * @param size 数据长度（字节）
 * @return int 0 表示操作成功；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败
 */
__static_inline int nor_write(storage_nor_t nor_hdl, uint32_t addr, const void *src, uint32_t size)
{
    if (nor_hdl)
        return nor_hdl->api.write(nor_hdl, addr, src, size);
    return -1;
}

/**
 * @brief 读取数据
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @param dest 用于保存数据的内存
 * @param addr 待读取数据的起始地址
 * @param size 数据长度（字节）
 * @return int 0 表示操作成功；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败
 */
__static_inline int nor_read(storage_nor_t nor_hdl, void *dest, uint32_t addr, uint32_t size)
{
    if (nor_hdl)
        return nor_hdl->api.read(nor_hdl, dest, addr, size);
    return -1;
}

/**
 * @brief 异步读取数据
 *
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @param dest 用于保存数据的内存
 * @param addr 待读取数据的起始地址
 * @param size 数据长度（字节）
 * @param hook 本次数据读取完毕后执行的回调函数
 * @return int 0 表示操作成功；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败
 */
__static_inline int nor_read_async(storage_nor_t nor_hdl, void *dest, uint32_t addr, uint32_t size, storage_nor_read_cb cb, void *arg)
{
    if (nor_hdl)
        return nor_hdl->api.read_async(nor_hdl, dest, addr, size, cb, arg);
    return -1;
}

/**
 * @brief 查询忙状态
 * 
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @return int 0 表示空闲；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败；
 */
__static_inline int nor_is_busy(storage_nor_t nor_hdl)
{
    if (nor_hdl)
        return nor_hdl->api.is_busy(nor_hdl);
    return -1;
}

/**
 * @brief 使设备进入或退出低功耗模式
 * 
 * @param nor_hdl 已被 nor_init() 初始化的的对象
 * @param power_on false -- 使掉电； true -- 使上电
 * @return int 0 表示空闲；
 * @return int 1 表示设备忙；
 * @return int -1 表示对象无效或操作失败；
 */
__static_inline int nor_set_power(storage_nor_t nor_hdl, bool power_on)
{
    if (nor_hdl)
        return nor_hdl->api.set_power(nor_hdl, power_on);
    return -1;
}

#ifdef __cplusplus
} /* extern "C" */
#endif /* #ifdef __cplusplus */

#endif
